/*
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* openUBMC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*         http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#include <gtest/gtest.h>
#include <devmon/driver_abi.h>
#include <mc/engine.h>
#include <test_utilities/test_base.h>
#include <mc/common.h>
#include <dlfcn.h>
#include <unordered_map>
#include <memory>

namespace drivers {
namespace pcie_gpu_card {
namespace innosilicon {
namespace awm_m11p_test {

// Service stub
class awm_m11p_test_service : public mc::engine::service {
public:
    awm_m11p_test_service(const std::string& name) : mc::engine::service(name) {}
};

// Test fixture
class AwmM11pAbiTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = std::make_unique<awm_m11p_test_service>("bmc.openubmc.test_awm_m11p");
        m_test_service->init();
        m_test_service->start();
        load_driver();
    }
    static void TearDownTestSuite() {
        m_test_service->stop();
        if (m_driver_handle != nullptr) {
            dlclose(m_driver_handle);
            m_driver_handle = nullptr;
        }
        TestWithEngine::TearDownTestSuite();
    }
    void SetUp() override {}
    void TearDown() override {}

    // Driver loading (dlopen + dlsym)
    static void load_driver() {
        // 注意：实际场景请确保路径正确！也可以配置为构建产物目录 opt/bmc/drivers/libawm_m11p.so
        m_driver_handle = dlopen("./opt/bmc/drivers/libawm_m11p.so", RTLD_LAZY);
        ASSERT_NE(m_driver_handle, nullptr) << "dlopen failed: " << dlerror();
        register_device_driver_func func = reinterpret_cast<register_device_driver_func>(
            dlsym(m_driver_handle, "register_device_driver"));
        ASSERT_TRUE(func != nullptr) << "dlsym failed: " << dlerror();
        device_driver_t* devices = nullptr;
        uint8_t count = 0;
        status_t ret = func(&devices, &count);
        ASSERT_EQ(ret, STATUS_OK);
        m_devices.clear();
        m_devices.reserve(count);
        for (uint8_t i = 0; i < count; ++i) {
            auto dev = std::make_shared<device_driver_t>(devices[i]);
            m_devices.emplace(dev->device_name, dev);
        }
    }

    // 构造测试用连接器对象
    mc::dict create_test_connector() {
        return mc::dict{{"SystemId", 1}};
    }
    // 测试服务
    static std::unique_ptr<awm_m11p_test_service> m_test_service;
    // 驱动符号表
    static std::unordered_map<std::string, std::shared_ptr<device_driver_t>> m_devices;
    static void* m_driver_handle;
};
std::unique_ptr<awm_m11p_test_service> AwmM11pAbiTest::m_test_service;
std::unordered_map<std::string, std::shared_ptr<device_driver_t>> AwmM11pAbiTest::m_devices;
void* AwmM11pAbiTest::m_driver_handle = nullptr;

// ----- 驱动注册、结构完整性 -----
TEST_F(AwmM11pAbiTest, DriverRegistrationAndStructure) {
    // 驱动包含三种类型
    EXPECT_EQ(m_devices.size(), 3);
    EXPECT_TRUE(m_devices.count("PCIeGpuCard") > 0);
    EXPECT_TRUE(m_devices.count("Gpu") > 0);
    EXPECT_TRUE(m_devices.count("Memory") > 0);
    // 结构完整性
    for (const auto& kv : m_devices) {
        EXPECT_TRUE(kv.second->ctor != nullptr);
        EXPECT_TRUE(kv.second->init != nullptr);
        EXPECT_TRUE(kv.second->start != nullptr);
        EXPECT_TRUE(kv.second->stop != nullptr);
    }
}
// ----- create 异常与空参数 -----
TEST_F(AwmM11pAbiTest, CreateInvalidArgsReturnNull) {
    for (auto&& it : m_devices) {
        auto drv = it.second;
        EXPECT_EQ(drv->ctor(nullptr, "x"), nullptr);
    }
}
// ----- create 正常分支 -----
TEST_F(AwmM11pAbiTest, CreateEachDeviceSuccess) {
    for (auto&& it : m_devices) {
        void* instance = it.second->ctor(m_test_service.get(), it.first.c_str());
        EXPECT_NE(instance, nullptr);
    }
}
// ----- create/init/start/stop 主流程&异常 ----
TEST_F(AwmM11pAbiTest, FullLifecycleNormalAndError) {
    for (auto&& it : m_devices) {
        auto drv = it.second;
        void* inst = drv->ctor(m_test_service.get(), ("full_"+it.first).c_str());
        ASSERT_NE(inst, nullptr);
        mc::mutable_dict config;
        mc::dict conn = create_test_connector();
        // 正常init
        status_t ret = drv->init(inst, &config, &conn);
        EXPECT_TRUE(ret == STATUS_OK || ret == STATUS_ERROR);
        // 正常start stop
        EXPECT_EQ(drv->start(inst), STATUS_OK);
        EXPECT_EQ(drv->stop(inst), STATUS_OK);
    }
}
// ----- 多实例/多类型批量测试 -----
TEST_F(AwmM11pAbiTest, MultiInstanceMultiType) {
    for (auto&& it : m_devices) {
        for (int i = 0; i < 3; ++i) {
            void* handle = it.second->ctor(m_test_service.get(), (it.first + std::to_string(i)).c_str());
            EXPECT_NE(handle, nullptr);
        }
    }
}
// ----- 属性基本校验（类型正确即可） -----
TEST_F(AwmM11pAbiTest, BasicObjectSanity) {
    auto card = m_devices["PCIeGpuCard"]->ctor(m_test_service.get(), "card_obj");
    auto gpu  = m_devices["Gpu"]->ctor(m_test_service.get(), "gpu_obj");
    auto mem  = m_devices["Memory"]->ctor(m_test_service.get(), "mem_obj");
    EXPECT_NE(card, nullptr);
    EXPECT_NE(gpu, nullptr);
    EXPECT_NE(mem, nullptr);
}

} // namespace awm_m11p_test
} // namespace innosilicon
} // namespace pcie_gpu_card
} // namespace drivers
